// FluxValidator - Ajax Form Validation for Rails
// Copyright (c) 2007 Peter Gumeson
// Contributors:
// 
// FluxValidator is freely distributable under the terms of an MIT license
// Project Home: http://fluxvalidator.googlecode.com

if (typeof Prototype == 'undefined' || parseFloat(Prototype.Version) < 1.5) {
  alert('FluxValidator requires the Prototype javascript library version 1.5.0 or greater. ' +
        'Check to make sure prototype.js is loaded before flux_validator.js');
}
if (typeof LowPro == 'undefined' || parseFloat(LowPro.Version) < 0.4) {
  alert('FluxValidator requires the LowPro javascript library version 0.4 or greater. ' +
        'Check to make sure lowpro.js is loaded before flux_validator.js');
}
if (typeof Effect == 'undefined') {
  alert('FluxValidator requires the Scriptaculous javascript library. ' +
        'Check to make sure effects.js is loaded before flux_validator.js');
}

FluxValidator = {
  form: null,
  source: null,
  Base: {
    initialize : function(options) {
      this.options = Object.extend({
        evaluateScripts: true
      }, options || {});
    },
    makeRequest : function(options) {
      if (options.update) new Ajax.Updater(options.update, options.url, options);
      else new Ajax.Request(options.url, options);
      return false;
    }
  }
};

// Handle form validation
FluxValidator.Validate = Behavior.create({
  onchange : function(e) {
    FluxValidator.form = this.element;
    FluxValidator.source = Event.element(e).id.replace(/_([0-9]+)i$/, '');
    
    var fieldSpan = $(FluxValidator.source+'_field');
    if (fieldSpan != null) {
      if (!fieldSpan.hasClassName('fieldWithErrors') &&
          !fieldSpan.hasClassName('fieldWithoutErrors')) {
        fieldSpan.addClassName('fieldWithoutErrors');
      }
    }
    var errorSpan = $(FluxValidator.source+'_errors');
    if (errorSpan != null) {
      if (!errorSpan.hasClassName('formErrors')) {
        errorSpan.addClassName('formErrors');
        errorSpan.setStyle({display: 'none'});
      }
    }
    
    var errorSpanHtml = '<span id="'+FluxValidator.source+'_errors" class="formErrors" style="display: none;"></span>';
    var elementType = Event.element(e).type;
    
    if (elementType == 'radio' || elementType == 'checkbox') {
      if (errorSpan == null) {
        nextSibling = Event.element(e).up().next();
        if (elementType == 'checkbox' && nextSibling.type == 'hidden') {
          nextSibling = nextSibling.next();
        }
        if (nextSibling != undefined ) {
          if( nextSibling.tagName == 'BR') {
            new Insertion.After(nextSibling, errorSpanHtml);
          }
          else {
            new Insertion.Before(nextSibling, errorSpanHtml);
          }
        }
        else {
          new Insertion.Bottom(Event.element(e).up(1), errorSpanHtml);
        }
      }
      
      if (elementType == 'radio') {
        radioPrefix = Event.element(e).name.sub(/^([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]$/, "#{1}_#{2}");
        errorSpan = $(radioPrefix+'_errors');
        if (errorSpan != null) {
          if (!errorSpan.hasClassName('formErrors')) {
            errorSpan.addClassName('formErrors');
            errorSpan.setStyle({display: 'none'});
          }
        }
        else {
          errorSpanHtml = '<span id="'+radioPrefix+'_errors" class="formErrors" style="display: none;"></span>';
          lastRadio = FluxValidator.form.getInputs('radio', Event.element(e).name).last();
          nextSibling = lastRadio.up().next('span');
          if (nextSibling != undefined) {
            new Insertion.Before(nextSibling, errorSpanHtml);
          }
          else {
            new Insertion.Bottom(lastRadio.up(1), errorSpanHtml);
          }
        }
      }
    }
    else if (errorSpan == null) {
      new Insertion.After(fieldSpan, errorSpanHtml);
    }
    
    var path = $F(FluxValidator.form['_validation']);
    var queryString = Form.serializeElements(Form.getElements(FluxValidator.form), false);
    queryString = queryString.replace(/(_?)method=([a-z]+)&/, '');
    
    var options = Object.extend({
      url: path,
      method: 'post',
      parameters: queryString
    }, this.options);
    return this.makeRequest(options);
  }
});
Object.extend(FluxValidator.Validate.prototype, FluxValidator.Base);

// Define some new Element methods
Element.addMethods({
  wrap: function(element, tagName) {
    element = $(element);
    var wrapper = document.createElement(tagName);
    element.up().replaceChild(wrapper, element);
    wrapper.appendChild(element);
    return Element.extend(wrapper);
  },
  equals: function(element, html) {
    element = $(element).innerHTML.stripScripts().stripTags();
    html = html.stripScripts().stripTags();
    return (element == html);
  }
});

// Override Scriptaculous Shake
Effect.Shake = function(element,valx) {
  element = $(element);
  valx = $(valx);
  nvalx = $(valx * (-1));
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left') };
    return new Effect.Move(element, 
      { x: (valx * 2) , y: 0, duration: 0.1, afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: (nvalx * 2), y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  (valx * 2), y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: (nvalx * 2), y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  (valx), y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: valx, y: 0, duration: 0.08, afterFinishInternal: function(effect) {
        effect.element.undoPositioned();
        effect.element.setStyle(oldStyle);
  valx = 0;
  nvalx = 0;
  }}) }}) }}) }}) }}) }});
}
